﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System;
using LitJson;
/// <summary>
/// 服务器
/// </summary>
public class Server : MonoBehaviour
{
    private static Server instance;

    public static Server Instance
    {
        get
        {
            return instance;
        }
    }

    private void Awake()
    {
        DontDestroyOnLoad(this.gameObject);
        instance = this;
    }

    private Socket server;

    //所有连接的客户端
    public List<TcpSocket> clients;


    private bool isLoopAccept = true;
    // Use this for initialization
    void Start()
    {
        //  服务器socket        协议族   
        server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        //绑定端口号
        server.Bind(new IPEndPoint(IPAddress.Any, MessageManager.port));
        //可以监听的客户端数目
        server.Listen(100);

        //开辟一个线程   处理客户端连接请求
        Thread listenThread = new Thread(ReceiveClient);
        //开启线程
        listenThread.Start();
        //后台运行
        listenThread.IsBackground = true;

        clients = new List<TcpSocket>();
    }

    /// <summary>
    /// 接受客户端连接的请求
    /// </summary>
    private void ReceiveClient()
    {
        while (isLoopAccept)
        {
            //开始接受客户端连接请求
            server.BeginAccept(AcceptClient, null);

            Debug.Log("检测客户端连接中.....");

            //每隔1s检测 有没有连接我
            Thread.Sleep(1000);

        }

    }

    private void OnApplicationQuit()
    {
        isLoopAccept = false;

        if (server != null && server.Connected)
        {
            server.Close();
        }

    }

    /// <summary>
    /// 客户端连接成功之后得回调
    /// </summary>
    /// <param name="ar"></param>
    private void AcceptClient(IAsyncResult ar)
    {
        Socket client = server.EndAccept(ar);

        TcpSocket clientSocket = new TcpSocket(client, 1024, true);
        clients.Add(clientSocket);

        Debug.Log("连接成功");
    }
    private void Update()
    {
        if (clients != null && clients.Count >= 0)
        {
            for (int i = 0; i < clients.Count; i++)
            {
                //监听每个服务器(连接的)发送的信息
                clients[i].ClientReceive();
            }
        }
        DisposeMessage();
    }
    /// <summary>
    /// 帧操作发送携程
    /// </summary>
    /// <returns></returns>
    IEnumerator enumeratorStart()
    {
        //发送空值提示帧同步开始
        Info info0 = new Info();
        info0.infoType = 3;
        info0.operation = new Operation();
        info0.operation.frameIndex = OperationController.Instance.frameIndex;
        string msg0 = JsonMapper.ToJson(info0);
        foreach (TcpSocket item in clients)
        {
            item.ClientSend(msg0);
        }
        while (true)
        {
            yield return new WaitForSeconds(0.1f);
            Info info = new Info();
            info.infoType = 3;
            info.operation = new Operation();
            info.operation.frameIndex = OperationController.Instance.frameIndex;
            if(OperationController.Instance.operationBackups.ContainsKey(OperationController.Instance.frameIndex)) info.operation.operationInfos = OperationController.Instance.operationBackups[OperationController.Instance.frameIndex];
            string msg = JsonMapper.ToJson(info);
            foreach (TcpSocket item in clients)
            {
                item.ClientSend(msg);
            }
            OperationController.Instance.frameIndex++;
        }
    }
    /// <summary>
    /// 处理接收到的消息
    /// </summary>
    public void DisposeMessage()
    {
        foreach (TcpSocket item in clients)
        {
            if(item.queue.Count != 0)
            {
                string message = (string)item.queue.Dequeue();
                Info info = JsonMapper.ToObject<Info>(message);
                switch (info.infoType)
                {
                    case 0:
                        break;
                    case 1:
                        bool isStart = true;
                        item.isStart = true;
                        for (int i = 0; i < clients.Count; i++)
                        {
                            if (!clients[i].isStart) isStart = false;
                        }
                        if(isStart) StartCoroutine(nameof(enumeratorStart));
                        break;
                    case 2:
                        break;
                    case 3:
                        OperationController.Instance.ServerOperationSet(info.operation);
                        break;
                    default:
                        break;
                }
            }
        }
    }
}

